package com.smsc.headend.task.engine.handler.impl.firmware;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.smsc.headend.common.enums.errorcode.TaskExecuteErrorCode;
import com.smsc.headend.common.enums.errorcode.TaskHandlerErrorCode;
import com.smsc.headend.module.fwu.entity.TemplateFwUpgrade;
import com.smsc.headend.module.protocol.DeviceData;
import com.smsc.headend.module.protocol.cosem.bo.CosemData;
import com.smsc.headend.module.task.dto.AtomicTask;
import com.smsc.headend.module.task.dto.AtomicTaskState;
import com.smsc.headend.module.task.dto.Task;
import com.smsc.headend.task.engine.dao.TaskDAO;
import com.smsc.headend.task.engine.exception.UDISTaskHandlerException;
import com.smsc.headend.task.engine.handler.TaskHandler;
import com.smsc.headend.task.engine.service.CosemXmlService;
import com.smsc.headend.task.engine.service.firmware.FirmwareService;
import com.smsc.headend.task.engine.utils.TaskParamUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.util.Map;

/**
 * @author liangli
 * @date 2020/9/25
 */
public class ReadFirmwareBlockSizeHandler implements TaskHandler {
    @Autowired
    CosemXmlService cosemXmlService;
    @Autowired
    TaskDAO taskDAO;
    @Value("#{T(java.lang.Integer).parseInt('${fwu.step.retryTimes:2}')}")
    Integer firmwareStepsRetry;
    @Autowired
    FirmwareService firmwareService;

    @Override
    public int handle(Task task, AtomicTask atomicTask, DeviceData deviceData, String actionResult) throws UDISTaskHandlerException {
        if (!(deviceData instanceof CosemData)) {
            throw new UDISTaskHandlerException(TaskHandlerErrorCode.DEVICE_DATA_TYPE_NOT_SUPPORT.toString());
        }

        CosemData cosemData = (CosemData) deviceData;
        Integer blockSize = Convert.toInt(cosemXmlService.getData(cosemData.getType(), cosemData.getValue()));
        log.info("Image Transfer: meterId={}, taskNo={}, get block size={}", task.getMeterId(), task.getTaskNo(), blockSize);
        taskDAO.addTaskData(task.getTaskNo(), atomicTask.getAtomicTaskNo(), "blockSize", blockSize, null, true);
        return 1;
    }

    @Override
    public int handleFailure(Task task, AtomicTask atomicTask, String message) {
        if (firmwareService.isRetryMessageType(message)) {
            AtomicTaskState atomicTaskState = taskDAO.hashGetAtomicTaskState(atomicTask.getAtomicTaskNo());
            if (atomicTaskState.getRetryTimes() >= firmwareStepsRetry) {
                log.error("Image transfer failed retry times over");
                firmwareService.saveFwuReport(task, atomicTask, -1, TemplateFwUpgrade.TaskType.ImageTransfer, StrUtil.format("confirm failed , {}", message), null);
                return -1;
            }
            log.error("Image transfer failed retry times {}", atomicTaskState.getRetryTimes());
            atomicTaskState.setStored(false);
            taskDAO.hashSetAtomicTaskState(atomicTask.getAtomicTaskNo(), task, atomicTaskState.getRetryTimes() + 1,  atomicTaskState);
            return 0;
        }
        firmwareService.saveFwuReport(task, atomicTask, -1, TemplateFwUpgrade.TaskType.ImageTransfer, StrUtil.format("confirm failed , {}", message), null);
        Map<String, Object> param = TaskParamUtils.getParameterMap(task, atomicTask);
        log.error("ImageTransfer: blokSizeFailed,meterId={},taskNo={},msg:{},param {}", task.getMeterId(), task.getTaskNo(), message, JSONUtil.toJsonStr(param));
        return -1;
    }
}
